package com.ruoyi.web.controller.order;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.*;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.BuffetMapper;
import com.ruoyi.system.mapper.NormalMapper;
import com.ruoyi.system.mapper.ReplaceMapper;
import com.ruoyi.system.mapper.RestaurantGoodsMapper;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.req.NormalDTO;
import com.ruoyi.system.service.resp.RestaurantOrderDetailDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Api("订单详情")
@RestController
@RequestMapping("/order/normal/detail")
public class NormalOrderDetailController extends BaseController {

    @Resource
    private NormalExamineService normalExamineService;

    @Resource
    private NormalExamineDetailService normalExamineDetailService;

    @Resource
    private RestaurantOrderDetailService restaurantOrderDetailService;

    @Resource
    private RestaurantOrderService restaurantOrderService;

    @Resource
    private NormalService normalService;

    @Resource
    private RestaurantGoodsService restaurantGoodsService;

    @Resource
    private NormalMapper normalMapper;

    @Resource
    private BuffetMapper buffetMapper;

    @Resource
    private ReplaceMapper replaceMapper;

    @Resource
    private RestaurantGoodsMapper restaurantGoodsMapper;

    @Resource
    private RestaurantStoreResourceService restaurantStoreResourceService;

    @ApiOperation("获取订单详情 分页")
    @Log(title = "网上订单详情", businessType = BusinessType.OTHER)
    @GetMapping("/list")
    public TableDataInfo list(RestaurantOrderDetail restaurantOrderDetail) {
        startPage();
        List<RestaurantOrderDetail> list = restaurantOrderDetailService.getNormalOrderDetailList(restaurantOrderDetail);
        return getDataTable(fillToDTO(list));
    }


    @Log(title = "网上订单详情All", businessType = BusinessType.OTHER)
    @GetMapping("/listNormalAll")
    public TableDataInfo listNormalAll(Normal normal) {
        List<Normal> list = normalService.selectList(normal);
        return getDataTable(fillToDTO1(list));
    }


    @Log(title = "订单详情", businessType = BusinessType.OTHER)
    @GetMapping("/listAll")
    public TableDataInfo listAll(RestaurantOrderDetail restaurantOrderDetail) {
        List<RestaurantOrderDetail> list = restaurantOrderDetailService.getNormalOrderDetailList(restaurantOrderDetail);
        return getDataTable(fillToDTO(list));
    }

    @Log(title = "订单详情-打印小票", businessType = BusinessType.OTHER)
    @GetMapping("/listPrint")
    public AjaxResult listPrint(RestaurantOrderDetail restaurantOrderDetail) {
        List<RestaurantOrderDetail> list = restaurantOrderDetailService.getNormalOrderDetailList(restaurantOrderDetail);
        List<RestaurantOrderDetailDTO> res = fillToDTO(list);
        for (RestaurantOrderDetailDTO detail : res) {
            if (detail.getPrice() != null) {
                detail.setPrice(detail.getPrice().setScale(2));
                if (detail.getCount() != null) {
                    detail.setMoney((new BigDecimal(detail.getCount()).multiply(detail.getPrice())).setScale(2));
                }
            }
        }

        RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(restaurantOrderDetail.getOrderId());
        if (restaurantOrder != null && StringUtils.isNotBlank(restaurantOrder.getType()) && restaurantOrder.getType().equals("buffet")) {
            if (CollectionUtils.isEmpty(res)) {
                RestaurantOrderDetailDTO restaurantOrderDetailDTO = new RestaurantOrderDetailDTO();
                restaurantOrderDetailDTO.setGoodsName("自助餐");
                restaurantOrderDetailDTO.setCount(1);
                restaurantOrderDetailDTO.setPrice(restaurantOrder.getAmount());
                res.add(restaurantOrderDetailDTO);
            }
        }

        return AjaxResult.success(res);
    }

    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable Long id) {
        return success(fillOneToDTO(restaurantOrderDetailService.selectNormalOrderDetailById(id)));
    }

    @ApiOperation("新增 订单详情")
    @Log(title = "网上订单详情", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody RestaurantOrderDetail restaurantOrderDetail) {
        List<RestaurantOrderDetail> details = restaurantOrderDetailService.getNormalOrderDetailList(restaurantOrderDetail);
        if (!CollectionUtils.isEmpty(details)) {
            RestaurantOrderDetail detail = details.get(0);
            detail.setCount(detail.getCount() + 1);
            detail.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
            Boolean result = restaurantOrderDetailService.updateNormalDetailOrderByCondition(detail);
            if (!result) {
                return error();
            }
            Long orderId = restaurantOrderDetail.getOrderId();
            RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(orderId);
            if ("购物车".equals(restaurantOrder.getStatus()) || "待付款".equals(restaurantOrder.getStatus())) {
                return success();
            }
        } else {
            restaurantOrderDetail.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
            Boolean result = restaurantOrderDetailService.createNormalDetailOrder(restaurantOrderDetail);
            if (!result) {
                return error();
            }
            Long orderId = restaurantOrderDetail.getOrderId();
            RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(orderId);
            if ("购物车".equals(restaurantOrder.getStatus()) || "待付款".equals(restaurantOrder.getStatus())) {
                return success();
            }
        }
        handleExamine(restaurantOrderDetail.getOrderId());
        return success();
    }

    public void handleExamine(Long orderId) {
        RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(orderId);
        if (restaurantOrder == null) {
            return;
        }
        // 非点餐订单不需要创建质检   点餐网上订单也需要生成
        if (!restaurantOrder.getType().contains("点餐网上订单")) {
            if (!restaurantOrder.getType().contains("点餐桌餐订单")) {
                return;
            }
        }

        PageUtils.clearPage();
        // 获取订单明细
        List<RestaurantOrderDetail> restaurantOrderDetails = restaurantOrderDetailService.getNormalOrderDetailList(RestaurantOrderDetail.builder()
                .orderId(orderId).build());
        if (CollectionUtils.isEmpty(restaurantOrderDetails)) {
            return;
        }
        List<Long> normalIds = restaurantOrderDetails.stream().map(RestaurantOrderDetail::getNormalId).collect(Collectors.toList());
        List<Normal> normals = normalMapper.selectByIds(normalIds);
        Set<Long> goodIds = normals.stream().map(Normal::getGoodsId).collect(Collectors.toSet());
        // 获取质检单明细
        NormalExamine normalExamine = normalExamineService.selectByOrderId(orderId);

        List<NormalExamineDetail> normalExamineDetails = new ArrayList<>();
        Map<Long, NormalExamineDetail> goodsIdExamineDetailMap = new HashMap<>();

        if (normalExamine != null && normalExamine.getId() != null) {
            normalExamineDetails = normalExamineDetailService.selectList(NormalExamineDetail.builder()
                    .examineId(normalExamine.getId()).build());

            if (!CollectionUtils.isEmpty(normalExamineDetails)) {
                goodsIdExamineDetailMap = normalExamineDetails.stream()
                        .filter(n -> n.getGoodsId() != null)
                        .collect(Collectors.toMap(NormalExamineDetail::getGoodsId, n -> n, (a1, a2) -> a1));
            }
        }
        // 没有的创建
        if (normalExamine != null && normalExamine.getId() != null) {
            for (Long goodsId : goodIds) {
                if (goodsIdExamineDetailMap.get(goodsId) != null) {
                    continue;
                }
                NormalExamineDetail examineDetailCreate = new NormalExamineDetail();
                examineDetailCreate.setExamineId(normalExamine.getId());
                examineDetailCreate.setGoodsId(goodsId);
                examineDetailCreate.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
                normalExamineDetailService.create(examineDetailCreate);
            }
        }
        // 多余的删除
        for (Long goodsId : goodsIdExamineDetailMap.keySet()) {
            if (goodIds.contains(goodsId)) {
                continue;
            }
            NormalExamineDetail examineDetail = goodsIdExamineDetailMap.get(goodsId);
            if (examineDetail != null) {
                normalExamineDetailService.deleteById(examineDetail.getId());
            }
        }
    }

    /**
     * h5接口
     *
     * @param restaurantOrderDetail
     * @return
     */
    @ApiOperation("编辑 订单详情")
    @Log(title = "网上订单详情", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody RestaurantOrderDetail restaurantOrderDetail) {
        List<RestaurantOrderDetail> details = restaurantOrderDetailService.getNormalOrderDetailList(restaurantOrderDetail);
        if (restaurantOrderDetail.getCount() == 0) {
            restaurantOrderDetailService.deleteNormalByIds(details.stream().map(RestaurantOrderDetail::getId).collect(Collectors.toList()));
            return success();
        }
        restaurantOrderDetail.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        Boolean result = restaurantOrderDetailService.updateNormalDetailOrderByCondition(restaurantOrderDetail);
        if (!result) {
            return error();
        }
        Long orderId = restaurantOrderDetail.getOrderId();
        RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(orderId);
        if ("购物车".equals(restaurantOrder.getStatus()) || "待付款".equals(restaurantOrder.getStatus())) {
            return success();
        }
        handleExamine(restaurantOrderDetail.getOrderId());
        return success();
    }

    /**
     * pc端接口
     *
     * @return
     */
    @Log(title = "网上订单详情", businessType = BusinessType.UPDATE)
    @PutMapping("/pcedit")
    public AjaxResult pcEdit(@Validated @RequestBody RestaurantOrderDetail restaurantOrderDetail) {
        List<RestaurantOrderDetail> details = restaurantOrderDetailService.getNormalOrderDetailList(restaurantOrderDetail);
        if (restaurantOrderDetail.getCount() == 0) {
            restaurantOrderDetailService.deleteNormalByIds(details.stream().map(RestaurantOrderDetail::getId).collect(Collectors.toList()));
            return success();
        }
        restaurantOrderDetail.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        Boolean result = restaurantOrderDetailService.updateNormalDetailOrder(restaurantOrderDetail);
        if (!result) {
            return error();
        }
        Long orderId = restaurantOrderDetail.getOrderId();
        RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(orderId);
        if ("待确定".equals(restaurantOrder.getStatus())) {
            return success();
        }
        handleExamine(restaurantOrderDetail.getOrderId());
        return success();
    }

    /**
     * pc端接口
     *
     * @return
     */
    @Log(title = "网上订单详情", businessType = BusinessType.DELETE)
    @GetMapping("/remove")
    public AjaxResult pcRemove(Long id) {
        RestaurantOrderDetail detail = restaurantOrderDetailService.selectNormalOrderDetailById(id);
        RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(detail.getOrderId());
        if ("已送达".equals(restaurantOrder.getStatus())) {
            return error("已送达的订单不能删除明细信息！");
        }
        restaurantOrderDetailService.deleteNormalOrderDetailById(id);
        pricecol(restaurantOrder);
        return success();
    }

    private void pricecol(RestaurantOrder restaurantOrder) {
        RestaurantOrderDetail restaurantOrderDetail = new RestaurantOrderDetail();
        restaurantOrderDetail.setOrderId(restaurantOrder.getId());
        List<RestaurantOrderDetail> normalOrderDetailList = restaurantOrderDetailService.getNormalOrderDetailList(restaurantOrderDetail);
        BigDecimal totalPrice = new BigDecimal(0);
        for (RestaurantOrderDetail detail : normalOrderDetailList) {
            totalPrice = totalPrice.add(detail.getPrice().multiply(new BigDecimal(detail.getCount())));
        }
        restaurantOrder.setAmount(totalPrice);
        restaurantOrderService.updateNormalOrder(restaurantOrder);
    }

    @ApiOperation("新增 订单详情pc")
    @Log(title = "pc订单详情", businessType = BusinessType.INSERT)
    @PostMapping("/addDetail")
    public AjaxResult addDetail(@RequestBody RestaurantOrderDetail restaurantOrderDetail) {
        RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(restaurantOrderDetail.getOrderId());
        if ("已送达".equals(restaurantOrder.getStatus())) {
            return error("已送达的订单不能新增明细信息！");
        }
        restaurantOrderDetailService.createNormalDetailOrder(restaurantOrderDetail);
        handleExamine(restaurantOrderDetail.getOrderId());
        return success();
    }

    @ApiOperation("修改 订单详情pc")
    @Log(title = "pc订单详情", businessType = BusinessType.INSERT)
    @PostMapping("/editDetail")
    public AjaxResult editDetail(@RequestBody RestaurantOrderDetail restaurantOrderDetail) {
        RestaurantOrder restaurantOrder = restaurantOrderService.selectNormalOrderById(restaurantOrderDetail.getOrderId());
        if ("已送达".equals(restaurantOrder.getStatus())) {
            return error("已送达的订单不能修改明细信息！");
        }
        restaurantOrderDetailService.updateNormalDetailOrder(restaurantOrderDetail);
        pricecol(restaurantOrder);
        return success();
    }


    @Log(title = "网上订单详情A", businessType = BusinessType.DELETE)
    @DeleteMapping("/{id}")
    public AjaxResult remove(@PathVariable Long id) {
        RestaurantOrderDetail restaurantOrderDetail = restaurantOrderDetailService.selectNormalOrderDetailById(id);
        if (restaurantOrderDetail == null) {
            return success();
        }
        Boolean result = restaurantOrderDetailService.deleteNormalOrderDetailById(id);
        if (!result) {
            return error();
        }
        handleExamine(restaurantOrderDetail.getOrderId());
        return success();
    }

    private List<RestaurantOrderDetailDTO> fillToDTO(List<RestaurantOrderDetail> restaurantOrderDetails) {
        if (CollectionUtils.isEmpty(restaurantOrderDetails)) {
            return new ArrayList<>();
        }
        return restaurantOrderDetails.stream().map(g -> {
            RestaurantOrderDetailDTO restaurantOrderDetailDTO = new RestaurantOrderDetailDTO();
            restaurantOrderDetailDTO.setId(g.getId());
            restaurantOrderDetailDTO.setGoodsId(g.getGoodsId());
            restaurantOrderDetailDTO.setBuffetId(g.getBuffetId());
            restaurantOrderDetailDTO.setNormalId(g.getNormalId());
            restaurantOrderDetailDTO.setReplaceId(g.getReplaceId());
            restaurantOrderDetailDTO.setOrderId(g.getOrderId());
//            restaurantOrderDetailDTO.setPrice(g.getPrice());

            restaurantOrderDetailDTO.setCreateBy(g.getCreateBy());
            restaurantOrderDetailDTO.setCreateTime(g.getCreateTime());
            restaurantOrderDetailDTO.setUpdateBy(g.getUpdateBy());
            restaurantOrderDetailDTO.setUpdateTime(g.getUpdateTime());
            restaurantOrderDetailDTO.setRemark(g.getRemark());
            if (g.getNormalId() != null) {
                Normal normal = normalMapper.selectById(g.getNormalId());
                if (normal != null && normal.getGoodsId() != null) {
                    RestaurantGoods restaurantGoods = restaurantGoodsMapper.selectRestaurantGoodsById(normal.getGoodsId());
                    restaurantOrderDetailDTO.setGoodsName(Optional.ofNullable(restaurantGoods).map(RestaurantGoods::getName).orElse(null));
                    restaurantOrderDetailDTO.setGoodsImageUrl(Optional.ofNullable(restaurantGoods).map(RestaurantGoods::getImage).orElse(null));
                    restaurantOrderDetailDTO.setPrice(normal.getPrice());
                }
            } else if (g.getBuffetId() != null) {
                Buffet buffet = buffetMapper.selectById(g.getBuffetId());
            } else if (g.getReplaceId() != null) {
                Replace replace = replaceMapper.selectById(g.getReplaceId());
                if (replace != null && replace.getResourceId() != null) {
                    RestaurantStoreResource resource = restaurantStoreResourceService.selectRestaurantStoreResourceById(replace.getResourceId());
                    restaurantOrderDetailDTO.setGoodsName(Optional.ofNullable(resource).map(RestaurantStoreResource::getName).orElse(null));
                    restaurantOrderDetailDTO.setGoodsImageUrl(Optional.ofNullable(resource).map(RestaurantStoreResource::getImageUrl).orElse(null));
                    restaurantOrderDetailDTO.setPrice(replace.getPrice());
                }
            }
            restaurantOrderDetailDTO.setCount(g.getCount());
            return restaurantOrderDetailDTO;
        }).collect(Collectors.toList());
    }

    private RestaurantOrderDetailDTO fillOneToDTO(RestaurantOrderDetail restaurantOrderDetail) {
        if (restaurantOrderDetail == null) {
            return null;
        }
        RestaurantOrderDetailDTO restaurantOrderDetailDTO = new RestaurantOrderDetailDTO();
        restaurantOrderDetailDTO.setId(restaurantOrderDetail.getId());
        restaurantOrderDetailDTO.setGoodsId(restaurantOrderDetail.getGoodsId());
        restaurantOrderDetailDTO.setBuffetId(restaurantOrderDetail.getBuffetId());
        restaurantOrderDetailDTO.setNormalId(restaurantOrderDetail.getNormalId());
        restaurantOrderDetailDTO.setReplaceId(restaurantOrderDetail.getReplaceId());
        restaurantOrderDetailDTO.setOrderId(restaurantOrderDetail.getOrderId());
        restaurantOrderDetailDTO.setCreateBy(restaurantOrderDetail.getCreateBy());
        restaurantOrderDetailDTO.setCreateTime(restaurantOrderDetail.getCreateTime());
        restaurantOrderDetailDTO.setUpdateBy(restaurantOrderDetail.getUpdateBy());
        restaurantOrderDetailDTO.setUpdateTime(restaurantOrderDetail.getUpdateTime());
        restaurantOrderDetailDTO.setRemark(restaurantOrderDetail.getRemark());
        RestaurantGoods restaurantGoods = restaurantGoodsService.selectById(restaurantOrderDetail.getGoodsId());
        if (restaurantGoods != null) {
            restaurantOrderDetailDTO.setGoodsName(restaurantGoods.getName());
        }
        return restaurantOrderDetailDTO;
    }

    private List<NormalDTO> fillToDTO1(List<Normal> normals) {
        if (CollectionUtils.isEmpty(normals)) {
            return new ArrayList<>();
        }
        List<Long> goodsIds = normals.stream().map(Normal::getGoodsId).collect(Collectors.toList());
        Map<Long, RestaurantGoods> goodsMap = restaurantGoodsService.selectByIds(goodsIds).stream().collect(Collectors.toMap(RestaurantGoods::getId, g -> g));
        return normals.stream().map(g -> {
            NormalDTO normalDTO = new NormalDTO();
            normalDTO.setId(g.getId());
            normalDTO.setPrice(g.getPrice());
            normalDTO.setGoodsId(g.getGoodsId());
            normalDTO.setStatus(g.getStatus());
            RestaurantGoods restaurantGoods = goodsMap.get(g.getGoodsId());
            if (restaurantGoods != null) {
//                normalDTO.setName(g.getName());
                normalDTO.setImage(restaurantGoods.getImage());
                normalDTO.setGoodsName(restaurantGoods.getName());
                normalDTO.setHot(restaurantGoods.getHot());
                normalDTO.setHun(restaurantGoods.getHun());
                normalDTO.setTaste(restaurantGoods.getTaste());
            }
            normalDTO.setCreateBy(g.getCreateBy());
            normalDTO.setCreateTime(g.getCreateTime());
            normalDTO.setUpdateBy(g.getUpdateBy());
            normalDTO.setUpdateTime(g.getUpdateTime());
            normalDTO.setRemark(g.getRemark());
            return normalDTO;
        }).collect(Collectors.toList());
    }


}
